package yunjiao.javatutorials.designpatterns.combinator;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * 创建一些最基础的 Combinator。它们是构建复杂验证器的“积木”
 *
 * @author yangyunjiao
 */
public class Validators {
    // 一个基础的 Combinator：它总是返回成功。
    // 这在组合时作为起点很有用。
    public static <T> Validator<T> valid() {
        return t -> ValidationResult.valid();
    }

    // 另一个基础 Combinator：根据一个条件（Predicate）和错误信息来创建验证器。
    public static <T> Validator<T> from(Predicate<T> predicate, String errorMessage) {
        return t -> predicate.test(t) ?
                ValidationResult.valid() :
                ValidationResult.invalid(errorMessage);
    }

    // 最重要的 Combinator：将两个验证器组合成一个新的。
    // 新的验证器会同时运行两个原始验证器，并合并它们的结果。
    public static <T> Validator<T> and(Validator<T> first, Validator<T> second) {
        return t -> {
            ValidationResult result1 = first.validate(t);
            ValidationResult result2 = second.validate(t);
            if (result1.isValid() && result2.isValid()) {
                return ValidationResult.valid();
            } else {
                // 合并错误列表
                List<String> errors = new ArrayList<>();
                errors.addAll(result1.getErrors());
                errors.addAll(result2.getErrors());
                return ValidationResult.invalid(errors);
            }
        };
    }

    // 另一个有用的 Combinator：OR 操作。如果其中一个验证通过则通过。
    public static <T> Validator<T> or(Validator<T> first, Validator<T> second) {
        return t -> {
            ValidationResult result1 = first.validate(t);
            ValidationResult result2 = second.validate(t);
            return result1.isValid() || result2.isValid() ?
                    ValidationResult.valid() :
                    // 这里可以更精细地处理错误信息
                    ValidationResult.invalid("Neither of the rules passed");
        };
    }
}
